package sch.frog.utils;

import java.util.LinkedList;

/**
 * 进制转换
 */
public class HexUtil {
	
	//十进制转任意进制整数部分
	private static String tenToAny(int num, int r) throws Exception {
		if(r > 36 || r <= 1){
			throw new IllegalArgumentException(r + " decimal can not be supported.");
		}
		
		boolean sign = num < 0;
		num = num > 0 ? num : -num;
		
		LinkedList<Integer> ll = new LinkedList<Integer>();
		while(num != 0) {
			ll.push(num % r);
			num /= r;
		}
		
		StringBuilder sb = new StringBuilder();
		while (!ll.isEmpty()) {
			int h = ll.pop();
			String str;
			if(h >= 10){
				str = (char)('A' + (h - 10)) + "";
			} else {
				str = Integer.toString(h);
			}
			sb.append(str);
		}
		
		if(sign){
			return "-" + sb.toString();
		}
		return sb.toString();
	}
	
	/**
	 * 任意进制转换为十进制
	 * @param num 需要转换的数字
	 * @param r	带转换数字的进制
	 * @return 转换出的十进制结果
	 * @throws Exception
	 */
	public static double any2Ten(String num, int r) throws Exception {
		if(r > 36 || r <= 1) {
			throw new IllegalArgumentException(r + " decimal can not be supported.");
		}
		
		String[] str = num.split("\\.");
		
		if(str.length > 2) return 0;
		
		double result = 0;
		for(int i = 0; i < str[0].length(); i++) {
			char ch = str[0].charAt(str[0].length() - 1 - i);
			if(ch >= 'A' && ch <= 'Z') {result += (ch - 'A' + 10) * Math.pow(r, i);}
			else if(ch >= '0' && ch <= '9') {result += (ch - '0') * Math.pow(r, i);}
			else{throw new IllegalArgumentException("can not be recognized : " + ch);}
		}
		
		if(str.length == 2){
			for(int i = 0; i < str[1].length(); i++) {
				char ch = str[1].charAt(i);
				if(ch >= 'A' && ch <= 'Z') {result += (ch - 'A' + 10) * Math.pow(r, (-1 - i));}
				else if(ch >= '0' && ch <= '9') {result += (ch - '0') * Math.pow(r, (-1 - i));}
				else { throw new IllegalArgumentException("can not be recognized : " + ch);}
			}
		}
		
		return result;
	}
	
	/**
	 * 十进制转换为任意进制
	 * @param num 十进制数
	 * @param r 目标进制
	 * @return 转换后的进制数
	 * @throws Exception
	 */
	public static String ten2Any(double num, int r) throws Exception {
		double dNum = num - (int)num;
		
		StringBuilder sb = new StringBuilder(tenToAny((int)num, r) + ".");
		
	
		int count = 0;
		while(dNum != 0){
			double d = dNum * r;
			if(d >= 10){
				sb.append((char)((int)d - 10 + 'A'));
			} else {
				sb.append((int)d);
			}
			dNum = d - (int)d;
			count++;
			if(count >= 100){break;}
		}
		
		return sb.toString();
	}
}
